package cn.elead.chaos.sso.server.web.login.helper;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.ui.Model;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import cn.elead.chaos.core.constant.Constants;
import cn.elead.chaos.core.util.StringUtils;
import cn.elead.chaos.framework.util.MessageUtils;
import cn.elead.chaos.sso.core.constant.SsoConstant;
import cn.elead.chaos.sso.core.user.LoginUser;
import cn.elead.chaos.sso.core.util.CookieUtil;
import cn.elead.chaos.sso.server.enums.ResponseType;
import cn.elead.chaos.sso.server.web.login.controller.LogController;
import cn.elead.chaos.sso.server.web.login.service.RedisSaveService;
import cn.elead.chaos.sso.server.web.login.vo.Login;
import cn.elead.chaos.sso.server.web.system.domain.SsoClient;
import cn.hutool.core.util.HexUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;

/**
 * 传统web登录
 * 
 * @author luopeng
 *
 */
@Component
public class SsoWebLoginHelper {

	@Autowired
	private RedisSaveService redisSaveService;

	/**
	 * 校验用户是否登录
	 * 
	 * @param request
	 * @param response
	 * @return
	 */
	public LoginUser loginCheck(HttpServletRequest request, HttpServletResponse response) {
		// 获取cookie
		String cookieSessionId = CookieUtil.getValue(request, SsoConstant.COOKIE_SESSIONID);
		if (StrUtil.isBlank(cookieSessionId)) {
			return null;
		}
		// 通过session获取redis中的用户
		LoginUser user = redisSaveService.getLoginUser(cookieSessionId);
		if (ObjectUtil.isNotNull(user)) {
			return user;
		}
		return user;
	}

	/**
	 * 保存信息
	 * 
	 * @param response
	 * @param sessionId
	 * @param user
	 * @param ifRemember
	 */
	public void login(HttpServletResponse response, String sessionId, LoginUser user, boolean ifRemember) {
		// 存储用户信息
		redisSaveService.saveLoginUserToRedis(sessionId, user);
		// 设置cookie
		CookieUtil.set(response, SsoConstant.COOKIE_SESSIONID, sessionId, ifRemember);
	}

	/**
	 * 清空信息
	 * 
	 * @param request
	 * @param response
	 */
	public void logout(HttpServletRequest request, HttpServletResponse response) {
		String cookieSessionId = CookieUtil.getValue(request, SsoConstant.COOKIE_SESSIONID);
		if (cookieSessionId == null) {
			return;
		}
		logout(request, response, cookieSessionId);
	}

	/**
	 * 清空信息
	 * 
	 * @param request
	 * @param response
	 */
	public void logout(HttpServletRequest request, HttpServletResponse response, String token) {
		redisSaveService.deleteLoginUserFromRedis(token);
		CookieUtil.remove(request, response, SsoConstant.COOKIE_SESSIONID);
	}

	/**
	 * 验证参数
	 * 
	 * @param attributes
	 * @param login
	 * @return
	 */
	public String vaildParam(HttpServletRequest request, RedirectAttributes attributes, Model model, SsoClient client, Login login) {
		String username = login.getUsername();
		String password = login.getPassword();
		// 校验用户和密码
		if (StringUtils.isBlank(username)) {
			return redirectLogin(request, attributes, model, client, "用户不能为空");
		}
		if (StringUtils.isBlank(password)) {
			return redirectLogin(request, attributes, model, client, "密码不能为空");
		}
		return null;
	}

	/**
	 * 重定向到登录页面
	 * 
	 * @param redirectAttributes
	 * @param client
	 * @param errorMsg
	 * @return
	 */
	public String redirectLogin(HttpServletRequest request, RedirectAttributes attributes, Model model, SsoClient client, String errorMsg) {
		attributes.addAttribute(SsoConstant.ERROR_MSG, errorMsg);
		setDefaultParam(attributes, request, client);
		setDefaultParam(model, request, client, errorMsg);
		return SsoConstant.REDIRECT_URI_PREFIX + StrUtil.SLASH + SsoConstant.LOGIN_PAGE;
	}

	/**
	 * 重定向到客户端系统
	 * 
	 * @param BaseController
	 * @param user
	 * @param responseType
	 * @param ifRemember
	 * @return
	 */
	public String redirectCodeCall(LogController controller, LoginUser user, SsoClient client, ResponseType responseType, boolean ifRemember) {
		Login login = new Login();
		login.setResponseType(responseType);
		login.setIfRemember(ifRemember);
		return redirectCodeCall(controller, user, login, client);
	}

	/**
	 * 重定向到客户端系统
	 * 
	 * @param BaseController
	 * @param user
	 * @param responseType
	 * @param ifRemember
	 * @return
	 */
	public String redirectCodeCall(LogController controller, LoginUser user, Login login, SsoClient client) {

		HttpServletRequest request = controller.getRequest();
		HttpServletResponse response = controller.getResponse();

		// 获取原来的session
		String cookieSessionId = CookieUtil.getValue(request, SsoConstant.COOKIE_SESSIONID);
		if (StrUtil.isBlank(cookieSessionId)) {
			// 重新生成session
			cookieSessionId = IdUtil.objectId();
		}
		// 先删除
		logout(request, response, cookieSessionId);
		// 再从新设置
		login(response, cookieSessionId, user, login.isIfRemember());

		// 登录日志
		controller.recordLogininfor(cookieSessionId, user.getLoginName(), Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success"));

		// 重定向到客户端系统
		String redirectUrl = request.getParameter(SsoConstant.REDIRECT_URI);
		if (redirectUrl != null && redirectUrl.trim().length() > 0) {

			// 模式
			ResponseType responseType = login.getResponseType();

			// code模式说明不是同一个域, 生成code
			if (responseType == ResponseType.CODE) {
				String code = HexUtil.encodeHexStr(SecureUtil.md5(client.getClientSecret()));
				redisSaveService.saveCodeToRedis(code, cookieSessionId);
				if(StrUtil.indexOfIgnoreCase(redirectUrl, "redirect_uri")!=-1) {
					redirectUrl += "&" + SsoConstant.SSO_CODE + "=" + code;
				}else {
					redirectUrl += "?" + SsoConstant.SSO_CODE + "=" + code;
				}
			}
			// 直接返回token
			if (responseType == ResponseType.TOKEN) {
				if(StrUtil.indexOfIgnoreCase(redirectUrl, "redirect_uri")!=-1) {
					redirectUrl += "&" + SsoConstant.SSO_TOKEN + "=" + cookieSessionId;
				}else {
					redirectUrl += "?" + SsoConstant.SSO_TOKEN + "=" + cookieSessionId;
				}
			}
			return SsoConstant.REDIRECT_URI_PREFIX + redirectUrl;
		} else {
			return SsoConstant.REDIRECT_URI_PREFIX + StrUtil.SLASH;
		}
	}

	/**
	 * 设置参数
	 * 
	 * @param attributes
	 * @param request
	 */
	public void setDefaultParam(RedirectAttributes attributes, HttpServletRequest request, SsoClient client) {
		attributes.addAttribute(SsoConstant.PARAM_CLIENT_ID, request.getParameter(SsoConstant.PARAM_CLIENT_ID));
		attributes.addAttribute(SsoConstant.PARAM_RESPONSE_TYPE, request.getParameter(SsoConstant.PARAM_RESPONSE_TYPE));
		attributes.addAttribute(SsoConstant.REDIRECT_URI, request.getParameter(SsoConstant.REDIRECT_URI));
	}

	/**
	 * 设置参数
	 * 
	 * @param attributes
	 * @param request
	 */
	public void setDefaultParam(Model model, HttpServletRequest request, SsoClient client) {
		// 进入登录页面
		setDefaultParam(model, request, client, org.apache.commons.lang3.StringUtils.EMPTY);
	}

	/**
	 * 设置参数
	 * 
	 * @param attributes
	 * @param request
	 */
	public void setDefaultParam(Model model, HttpServletRequest request, SsoClient client, String message) {
		// 进入登录页面
		model.addAttribute(SsoConstant.ERROR_MSG, message);
		model.addAttribute(SsoConstant.CLIENT, client);
		model.addAttribute(SsoConstant.PARAM_CLIENT_ID, request.getParameter(SsoConstant.PARAM_CLIENT_ID));
		model.addAttribute(SsoConstant.PARAM_RESPONSE_TYPE, request.getParameter(SsoConstant.PARAM_RESPONSE_TYPE));
		model.addAttribute(SsoConstant.REDIRECT_URI, request.getParameter(SsoConstant.REDIRECT_URI));
	}

	/**
	 * 主题
	 * 
	 * @param request
	 * @return
	 */
	public String getTheme(HttpServletRequest request, String theme) {
		if (StrUtil.isNotBlank(theme)) {
			return SsoConstant.THEME + theme;
		}
		String cookieTheme = CookieUtil.getValue(request, SsoConstant.COOKIE_THEME);
		if (StrUtil.isBlank(cookieTheme)) {
			return SsoConstant.DEFAULT_THEME;
		}
		return SsoConstant.THEME + cookieTheme;
	}

	/**
	 * 登录页面
	 * 
	 * @param request
	 * @return
	 */
	public String toLoginPage(HttpServletRequest request) {
		return toLoginPage(request, null);
	}

	/**
	 * 登录页面
	 * 
	 * @param request
	 * @return
	 */
	public String toLoginPage(HttpServletRequest request, String theme) {
		return getTheme(request, theme) + StrUtil.SLASH + SsoConstant.LOGIN_PAGE;
	}

}
